﻿
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Bot.Domain.Comm100OwnBot
{
    public interface IComm100OwnBotService
    {
        Task<string> TrainBotAsync(int siteId, Guid botId, TrainingData trainingData);
        Task<QueryTrainStatusResponse> QueryTrainStatusAsync(int siteId, Guid botId, string trainId);
        Task<List<QueryIntentResponse>> QueryIntentAsync(int siteId, Guid botId, QueryIntentData queryIntentData, int count);
        Task<Dictionary<string, List<string>>> IdentifyEntity(int siteId, Guid botId, QueryEntityData queryIntentData);
    }
    public class Comm100OwnBotService: IComm100OwnBotService
    {
        private bool Debug { get; } = false;
        private string baseUri=string.Empty;
        //{
        //    get
        //    {
        //        //string key = "NlpServer-Uri-CacheKey";
        //        //var result = Infrastructure.Utils.GetMemoryCache(key, () =>
        //        //{
        //        //    return Com.Comm100.Public.Common.ConfigOptionHelper.GetConfigOptionValueByKey("NlpServer");
        //        //}, 60 * 60 * 24);
        //        string result = Com.Comm100.Public.Common.ConfigOptionHelper.GetConfigOptionValueByKey("NlpServer");
        //        return result.TrimEnd('/');
        //    }
        //}

        public Comm100OwnBotService()
        {
#if DEBUG
            Debug = true;
#endif
            string result = ConfigOptionHelper.GetConfigOptionValueByKey("NlpServer");
            baseUri = result.TrimEnd('/');
        }

        public async Task<string> TrainBotAsync(int siteId, Guid botId, TrainingData trainingData)
        {
            string trainId = "";

            if (Debug)
            {
                trainId = Guid.NewGuid().ToString();
            }
            else
            {
                string uriString = baseUri + "/train?siteId={0}&botId={1}";
                uriString = string.Format(uriString, siteId, botId);

                string json = JsonConvert.SerializeObject(trainingData);
                //LogHelper.Error(JsonConvert.SerializeObject(new
                //{
                //    uriString,
                //    json,
                //}));
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
                {
                    RequestUri = new Uri(uriString),
                    Content = new StringContent(json, Encoding.UTF8, "application/json"),
                };
                HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage);
                string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
                //LogHelper.Error(strResult);
                if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    trainId = JsonConvert.DeserializeObject<dynamic>(strResult).trainId;
                }
                else
                {
                    throw new Exception(strResult);
                }
            }            
        
            return trainId;
        }
        public async Task<QueryTrainStatusResponse> QueryTrainStatusAsync(int siteId, Guid botId, string trainId)
        {
            QueryTrainStatusResponse response = new QueryTrainStatusResponse { };

            if (Debug)
            {
                response = new QueryTrainStatusResponse {
                    Status="done",
                    Trainid = trainId,
                };
            }
            else
            {
                string uriString = baseUri + "/trainStatus?siteId={0}&botId={1}&trainId={2}";
                uriString = string.Format(uriString, siteId, botId, trainId);

                //LogHelper.Error(JsonConvert.SerializeObject(new
                //{
                //    uriString,
                //}));
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
                {
                    RequestUri = new Uri(uriString),
                };
                HttpResponseMessage httpResponseMessage = await GetAsync(httpRequestMessage);
                string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
                //LogHelper.Error(strResult);
                if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    response = JsonConvert.DeserializeObject<QueryTrainStatusResponse>(strResult);
                }
                else
                {
                    throw new Exception(strResult);
                }
            }
            
            return response;
        }
        public async Task<List<QueryIntentResponse>> QueryIntentAsync(int siteId, Guid botId, QueryIntentData queryIntentData, int count)
        {
            List<QueryIntentResponse> queryIntentResponses = new List<QueryIntentResponse>();

            if (Debug)
            {
                queryIntentResponses = new List<QueryIntentResponse> {
                    new QueryIntentResponse
                    {
                        intent="intent1",
                        score=0.32m,
                    },
                    new QueryIntentResponse
                    {
                        intent="intent2",
                        score=0.01m,
                    },
                    new QueryIntentResponse
                    {
                        intent="intent3",
                        score=0.28m,
                    },
                    new QueryIntentResponse
                    {
                        intent="intent4",
                        score=0.02m,
                    },
                    new QueryIntentResponse
                    {
                        intent="intent5",
                        score=0.05m,
                    },
                };
            }
            else
            {
                string uriString = baseUri + "/queryIntent?siteId={0}&botId={1}&intentCount={2}";
                uriString = string.Format(uriString, siteId, botId, count);

                string json = JsonConvert.SerializeObject(queryIntentData);
                //LogHelper.Error(JsonConvert.SerializeObject(new
                //{
                //    uriString,
                //    json,
                //}));
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
                {
                    RequestUri = new Uri(uriString),
                    Content = new StringContent(json, Encoding.UTF8, "application/json"),
                };
                HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage);
                string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
                //LogHelper.Error(strResult);
                if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    queryIntentResponses = JsonConvert.DeserializeObject<List<QueryIntentResponse>>(strResult);
                }
                else
                {
                    throw new Exception(strResult);
                }
            }
            
            return queryIntentResponses;
        }
        public async Task<Dictionary<string, List<string>>> IdentifyEntity(int siteId, Guid botId, QueryEntityData queryIntentData)
        {
            Dictionary<string, List<string>> keyValues = new Dictionary<string, List<string>>();

            if (Debug)
            {
                keyValues = new Dictionary<string, List<string>> {
                    {"location",new List<string>{ "beijing","shanghai" } },
                    {"city",new List<string>{ "beijing","shanghai" } },
                    {"PERCENT",new List<string>{ "8%"} },
                    {"LANGUAGE",new List<string>{ "english"} },
                };

                //keyValues = new Dictionary<string, List<string>> { };
            }
            else
            {
                string uriString = baseUri + "/identifyEntity?siteId={0}&botId={1}";
                uriString = string.Format(uriString, siteId, botId);               
                string json = JsonConvert.SerializeObject(queryIntentData);
                //LogHelper.Error(JsonConvert.SerializeObject(new
                //{
                //    uriString,
                //    json,
                //}));
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
                {
                    RequestUri = new Uri(uriString),
                    Content = new StringContent(json, Encoding.UTF8, "application/json"),
                };
                HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage);
                string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
                //LogHelper.Error(strResult);
                if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    var result = JsonConvert.DeserializeObject<List<EntityResult>>(strResult);
                    foreach (var item in result)
                    {
                        if (keyValues.ContainsKey(item.name))
                        {
                            keyValues[item.name].Add(item.result);
                        }
                        else
                        {
                            keyValues.Add(item.name, new List<string>() { item.result });
                        }
                    }
                }
                else
                {
                    LogHelper.WriteExceptionLog(new Exception(strResult));
                }
            }

            return keyValues;
        }

        #region web method
        private async Task<HttpResponseMessage> GetAsync(HttpRequestMessage request, int timeout = 60)
        {
            HttpResponseMessage httpResponseMessage = null;
            request.Method = HttpMethod.Get;

            httpResponseMessage = await SendAsync(request, timeout);
            return httpResponseMessage;
        }
        private async Task<HttpResponseMessage> PostAsync(HttpRequestMessage request, int timeout = 60)
        {
            HttpResponseMessage httpResponseMessage = null;
            request.Method = HttpMethod.Post;
            httpResponseMessage = await SendAsync(request, timeout);
            return httpResponseMessage;
        }
        private async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, int timeout = 60)
        {
            HttpResponseMessage httpResponseMessage = null;
            using (var client = new HttpClient())
            {
                client.Timeout = TimeSpan.FromSeconds(timeout);                
                httpResponseMessage = await client.SendAsync(request);
                return httpResponseMessage;
            }
        }
        #endregion
    }

    public class EntityResult
    {
        public string sub_str { get; set; }
        public string name { get; set; }
        public string result { get; set; }
    }
}
